package agenda

object Meeting {
  def isValidSlotRange(firstSlot: Int, lastSlot: Int): Boolean = {
    SlottedEntry.isValidSlot(firstSlot) && SlottedEntry.isValidSlot(lastSlot) && (firstSlot <= lastSlot)
  }
}

class Meeting(_agenda: Agenda, private val _twinAgenda: Agenda, _day: Int, _subject: String, private var firstSlot: Int = 1,
  private var lastSlot: Int = 24) extends SlottedEntry(_agenda, _day, _subject) {
  require(canHaveAsDay(_day))
  require(SlottedEntry.isValidSlot(firstSlot))
  require(SlottedEntry.isValidSlot(lastSlot))
  require(firstSlot <= lastSlot)
  require(twinAgenda != null)

  if (Meeting.isValidSlotRange(firstSlot, lastSlot))
    setSlotRange(firstSlot, lastSlot)
  this.twinAgenda.addEntry(this)

  override def isOccupying_(isOccupying: Boolean): Unit = {
    _isOccupying = isOccupying
  }

  override def canHaveAsDay(day: Int): Boolean = {
    super.canHaveAsDay(day) && day % 7 != 0
  }

  override def getFirstSlot() = firstSlot
  override def getLastSlot() = lastSlot

  override protected def occupiesSlot(slot: Int): Boolean = {
    slot >= getFirstSlot() && slot <= getLastSlot()
  }

  private def setSlotRange(startSlot: Int, endSlot: Int): Unit = {
    require(Meeting.isValidSlotRange(startSlot, endSlot))
    firstSlot = startSlot
    lastSlot = endSlot
  }

  def twinAgenda = _twinAgenda

  override def mergeWith(other: Entry): Meeting = {
    require(other != null)
    require(this.day == other.day)
    require((!this.isTerminated()) && (!other.isTerminated()))
    require(this.agenda == other.agenda)
    require(other.isInstanceOf[Meeting])
    require(this.overlapsWith(other))
    val otherMeeting: Meeting = other.asInstanceOf[Meeting]
    subject = (this.subject + other.subject);
    this.setSlotRange(Math.min(this.getFirstSlot(), otherMeeting.getFirstSlot()), Math.max(this.getLastSlot(), otherMeeting.getLastSlot()));
    other.terminate();
    return this;
  }
}